﻿using System;
using System.Collections.Generic;
using System.Text;
using HR.Appointments.DataLayer;
using HR.Appointments.Service.ValueObjects;

namespace HR.Appointments.Service
{
    /// <summary>
    /// Entity class for reserved time
    /// </summary>
    public class ReservedTimeEntity
    {
        #region Member variable
        private int _id;
        private int _companyId;
        private CompanyEntity _company;
        private DateTime _from;
        private DateTime _to;
        private TimeUnit _fromTime;
        private TimeUnit _toTime;
        private bool _isRepeating;
        private int _workstationId;
        private WorkstationEntity _workstation;
        #endregion

        #region Constructors
        private ReservedTimeEntity(int id, int companyId, DateTime fromDate, DateTime toDate, 
            TimeUnit fromTime, TimeUnit toTime, bool isRepeating, int workstationId)
        {
            _id = id;
            _from = fromDate;
            _to = toDate;
            _isRepeating = isRepeating;
            _companyId = companyId;
            _workstationId = workstationId;
            _fromTime = fromTime;
            _toTime = toTime;
            _workstation = DAO.Instance.Workstation.GetInstance(_workstationId);
            _company = DAO.Instance.Company.GetInstance(companyId);
        }
        #endregion

        #region Properties
        /// <summary>
        /// Reserved Time identifier
        /// </summary>
        public int Id
        {
            get
            {
                return _id;
            }
        }

        /// <summary>
        /// From which date the reserved time is registered
        /// </summary>
        public DateTime FromDate
        {
            get
            {
                return _from;
            }
            set
            {
                _from = value; 
            }
        }

        /// <summary>
        /// To which date the reserved time is registered
        /// </summary>
        public DateTime ToDate
        {
            get
            {
                return _to; 
            }
            set
            {
                _to = value; 
            }
        }

        //TODO: Implement the is repeating value
        /// <summary>
        /// Not Implemented
        /// </summary>
        public bool IsRepeating
        {
            get
            {
                return _isRepeating; 
            }
            set
            {
                _isRepeating = value; 
            }
        }

        /// <summary>
        /// From which time the reserved time is registered
        /// </summary>
        public TimeUnit FromTime
        {
            get
            {
                return _fromTime;
            }
            set
            {
                _fromTime = value;
            }
        }

        /// <summary>
        /// To which date the reserved time is registered
        /// </summary>
        public TimeUnit ToTime
        {
            get
            {
                return _toTime;
            }
            set
            {
                _toTime = value;
            }
        }

        /// <summary>
        /// Workstation identifier
        /// </summary>
        public int WorkStationID
        {
            get { return _workstationId; }
        }

        /// <summary>
        /// Workstation name
        /// </summary>
        public string WorkstationName
        {
            get 
            {
                if (_workstation != null)
                {
                    return _workstation.Name;
                }
                return string.Empty;
            }
        }

        /// <summary>
        /// Workstation entity registered for this reserved time
        /// </summary>
        public WorkstationEntity Station
        {
            get { return _workstation; }
        }
        #endregion

        #region Public Methods
        internal List<TimeUnit> GetReservedSlots(DateTime date)
        {
            var result = new List<TimeUnit>();

            if (FromDate.CompareTo(date) <= 0 && ToDate.CompareTo(date) >= 0)
            {
                TimeUnit beginTime = (FromDate.CompareTo(date) < 0) ?
                    TimeUnit.Create(0, 0) : FromTime;

                TimeUnit endTime = (ToDate.CompareTo(date) > 0) ?
                    TimeUnit.Create(23, 59) : ToTime;

                TimeUnit currentTime = (TimeUnit)beginTime.Clone();
                while (currentTime.CompareTo(endTime) < 0)
                {
                    result.Add((TimeUnit)currentTime.Clone());
                    currentTime.Add(_company.SlotDuration);
                    
                    //Break if new day
                    if(currentTime.IsNextDay)
                        break;
                }
            }
            return result;
        }
        #endregion

        #region Internal Methods
        /// <summary>
        /// Convert this object to datalayer 
        /// </summary>
        /// <param name="data">Datalayer entity</param>
        /// <returns>A datalayer entity with this objects values</returns>
        internal ReservedHour ToData(ReservedHour data)
        {
            if (data == null)
            {
                data = new ReservedHour();
            }
            data.ToHour = _toTime.Hour;
            data.ToMinute = _toTime.Minute;
            data.ComanyId = _companyId;
            data.FromDate = _from;
            data.FromHour = _fromTime.Hour;
            data.FromMinute = _fromTime.Minute;
            data.IsRepeating = _isRepeating;
            data.ToDate = _to;
            data.WorkstationId = _workstationId;
            return data;
        }
        #endregion

        #region Override Methods
        /// <summary>
        /// Determines whether the specified Object is equal to the current Object.
        /// </summary>
        /// <param name="obj">The Object to compare with the current Object.</param>
        /// <returns>true if the specified Object is equal to the current Object; otherwise, false.</returns>
        public override bool Equals(object obj)
        {
            if (obj == null || GetType() != obj.GetType()) return false;
            ReservedTimeEntity eql = (ReservedTimeEntity)obj;
            return (eql._id == _id);
        }

        /// <summary>
        /// Serves as a hash function for a this type.
        /// </summary>
        /// <returns>A hash code for the current Object.</returns>
        public override int GetHashCode()
        {
            return _id.GetHashCode();
        }

        /// <summary>
        /// Returns a String that represents the current Object.
        /// </summary>
        /// <returns>A String that represents the current Object.</returns>
        public override string ToString()
        {
            return FromDate.ToShortDateString() + " " + FromTime.ToString() + " - "
                + ToDate.ToShortDateString() + " " + ToTime.ToString();
        }
        #endregion

        #region Static Members
        /// <summary>
        /// Loads a datalayer entity into a service entity.
        /// </summary>
        /// <param name="row"></param>
        /// <returns>A loaded entity</returns>
        internal static ReservedTimeEntity Load(HR.Appointments.DataLayer.ReservedHour row)
        {
            if (row == null) return null;
            return new ReservedTimeEntity(row.Id, row.ComanyId, row.FromDate, row.ToDate,
                TimeUnit.Create(row.FromHour, row.FromMinute),
                TimeUnit.Create(row.ToHour, row.ToMinute),
                row.IsRepeating, row.WorkstationId);
        }

        /// <summary>
        /// Creates a new entity
        /// </summary>
        /// <param name="companyId">Company identifier</param>
        /// <param name="fromDate">From which date</param>
        /// <param name="toDate">To which data</param>
        /// <param name="fromTime">From which time</param>
        /// <param name="toTime">To which time</param>
        /// <param name="isRepeating">Is the resered time repeatable (not implemented)</param>
        /// <param name="workstationId">Workstation identifier</param>
        /// <returns>A new entity</returns>
        public static ReservedTimeEntity Create(int companyId, DateTime fromDate, DateTime toDate,
            TimeUnit fromTime, TimeUnit toTime, bool isRepeating, int workstationId)
        {
            return new ReservedTimeEntity(0, companyId, fromDate, toDate, fromTime, toTime,
                isRepeating, workstationId);
        }
        #endregion
    }
}

